package conta;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import excecao.ExcecaoContaInexistente;
import excecao.ExcecaoFaltaEspaco;
import excecao.ExcecaoNumeroInvalido;
import excecao.ExcecaoSaqueInvalido;
import excecao.ExcecaoTipoConta;
import excecao.ExcecaoValorNegativo;

public class AgenciaTest {
	private Agencia agencia;

	@Before
	public void setUp() throws Exception {
		agencia = new Agencia();
	}

	@Test(expected = ExcecaoNumeroInvalido.class)
	public void abrirContaNumeroNegativo() {
		agencia.criarConta(-1, "conta 1", 100, (byte) 1, 0);
	}

	@Test(expected = ExcecaoValorNegativo.class)
	public void abrirContaSaldoNegativo() {
		agencia.criarConta(1, "conta 1", -100, (byte) 1, 0);
	}

	@Test
	public void abrirContaCorrente() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		Assert.assertEquals(100, agencia.getSaldo(1), 0);
	}

	@Test
	public void abrirContaPoupanca() {
		agencia.criarConta(2, "conta 2", 100, (byte) 2, 0);
		Assert.assertEquals(100, agencia.getSaldo(2), 0);
	}

	@Test
	public void abrirContaEspecial() {
		agencia.criarConta(3, "conta 3", 100, (byte) 3, 10);
		Assert.assertEquals(110, agencia.getSaldo(3), 0);
	}

	@Test
	public void cancelarConta() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		Assert.assertEquals(100, agencia.getSaldo(1), 0);
		agencia.cancelarConta(1);
	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void abrirContaInexistente() {
		agencia.cancelarConta(1);
	}

	@Test(expected = ExcecaoValorNegativo.class)
	public void abrirContaEspecialLimiteNegativo() {
		agencia.criarConta(3, "conta 3", 100, (byte) 3, -1);
	}

	@Test
	public void listarContasSemCobranca() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.criarConta(2, "conta 2", 100, (byte) 2, 0);
		agencia.criarConta(3, "conta 3", 100, (byte) 3, 10);

		agencia.listarContas();

		Assert.assertEquals(100, agencia.getSaldo(1), 0);
		Assert.assertEquals(100, agencia.getSaldo(2), 0);
		Assert.assertEquals(110, agencia.getSaldo(3), 0);
	}

	@Test
	public void listarContasComCobranca() {
		agencia.criarConta(2, "conta 2", 100, (byte) 2, 0);

		agencia.consultarConta(2);
		Assert.assertEquals(100, agencia.getSaldo(2), 0);
		agencia.consultarConta(2);
		agencia.consultarConta(2);
		Assert.assertEquals(98.9, agencia.getSaldo(2), 1);

	}

	@Test
	public void reajustarPoupanca() {
		agencia.criarConta(2, "conta 2", 100, (byte) 2, 0);
		agencia.reajustarPoupanca(2, 5);
		Assert.assertEquals(105, agencia.getSaldo(2), 1);
	}

	@Test(expected = ExcecaoTipoConta.class)
	public void reajustarDiferentePoupanca() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.reajustarPoupanca(1, 5);
	}

	@Test
	public void cobrarJurosEspecial() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 10);
		agencia.sacar(1, 101);
		agencia.cobrarJurosContaEspecial(1);
		Assert.assertEquals(9.92, agencia.getSaldo(1), 1);
	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void depositarContaInexistente() {
		agencia.depositar(1, 10);
	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void sacarCorrenteInexistente() {
		agencia.sacar(1, 10);
	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void reajustaPoupancaInexistente() {
		agencia.reajustarPoupanca(1, 10);
	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void cobrarManutencaoContaInexistente() {
		agencia.cobrarTarifa(1);
	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void cobrarJurosContaInexistente() {
		agencia.cobrarJurosContaEspecial(1);
	}

	@Test(expected = ExcecaoTipoConta.class)
	public void cobrarJurosNaoEspecial() {
		agencia.criarConta(1, "conta 1", 100, (byte) 2, 0);
		agencia.cobrarJurosContaEspecial(1);
	}

	@Test(expected = ExcecaoTipoConta.class)
	public void cobrarJurosCorrente() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.cobrarJurosContaEspecial(1);
	}

	@Test(expected = ExcecaoTipoConta.class)
	public void cobrarManutencaoPoupanca() {
		agencia.criarConta(1, "conta 1", 100, (byte) 2, 0);
		agencia.cobrarTarifa(1);
	}

	@Test
	public void cobrarManutencaoCorrente() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.cobrarTarifa(1);
		Assert.assertEquals(87.5, agencia.getSaldo(1), 1);
	}

	@Test(expected = ExcecaoSaqueInvalido.class)
	public void cobrarManutencaoCorrenteSaldoInsuficiente() {
		agencia.criarConta(1, "conta 1", 10, (byte) 1, 0);
		agencia.cobrarTarifa(1);
		System.out.println(agencia.getSaldo(1));
		Assert.assertEquals(-10, agencia.getSaldo(1), 1);
	}

	@Test
	public void cobrarManutencaoEspecial() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 0);
		agencia.cobrarTarifa(1);
		Assert.assertEquals(80, agencia.getSaldo(1), 1);
	}

	@Test
	public void depositarCorrente() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.depositar(1, 10);
		Assert.assertEquals(110, agencia.getSaldo(1), 1);
	}

	@Test
	public void depositarPoupanca() {
		agencia.criarConta(1, "conta 1", 100, (byte) 2, 0);
		agencia.depositar(1, 10);
		Assert.assertEquals(110, agencia.getSaldo(1), 1);
	}

	@Test
	public void depositarEspecial() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 0);
		agencia.depositar(1, 10);
		Assert.assertEquals(110, agencia.getSaldo(1), 1);
	}

	@Test
	public void sacarCorrente() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.sacar(1, 10);
		Assert.assertEquals(90, agencia.getSaldo(1), 1);
	}

	@Test
	public void sacarPoupanca() {
		agencia.criarConta(1, "conta 1", 100, (byte) 2, 0);
		agencia.sacar(1, 10);
		Assert.assertEquals(90, agencia.getSaldo(1), 1);
	}

	@Test
	public void sacarEspecial() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 0);
		agencia.sacar(1, 10);
		Assert.assertEquals(90, agencia.getSaldo(1), 1);
	}

	@Test
	public void sacarEspecialEmprestimo() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 10);
		agencia.sacar(1, 105);
		Assert.assertEquals(5, agencia.getSaldo(1), 1);
	}

	@Test(expected = ExcecaoSaqueInvalido.class)
	public void sacarCorrenteInvalido() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.sacar(1, 110);
	}

	@Test(expected = ExcecaoSaqueInvalido.class)
	public void sacarPoupancaInvalido() {
		agencia.criarConta(1, "conta 1", 100, (byte) 2, 0);
		agencia.sacar(1, 110);
	}

	@Test(expected = ExcecaoSaqueInvalido.class)
	public void sacarEspecialInvalido() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 0);
		agencia.sacar(1, 130);
	}

	@Test(expected = ExcecaoSaqueInvalido.class)
	public void sacarEspecialEmprestimoInvalido() {
		agencia.criarConta(1, "conta 1", 100, (byte) 3, 10);
		agencia.sacar(1, 155);
	}

	@Test
	public void abrirVinteContas() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.criarConta(2, "conta 2", 100, (byte) 2, 0);
		agencia.criarConta(3, "conta 3", 100, (byte) 3, 10);
		agencia.criarConta(4, "conta 4", 100, (byte) 1, 0);
		agencia.criarConta(5, "conta 5", 100, (byte) 2, 0);
		agencia.criarConta(6, "conta 6", 100, (byte) 3, 20);
		agencia.criarConta(7, "conta 7", 100, (byte) 1, 0);
		agencia.criarConta(8, "conta 8", 100, (byte) 2, 0);
		agencia.criarConta(9, "conta 9", 100, (byte) 3, 30);
		agencia.criarConta(10, "conta 10", 100, (byte) 1, 0);
		agencia.criarConta(11, "conta 11", 100, (byte) 2, 0);
		agencia.criarConta(12, "conta 12", 100, (byte) 3, 40);
		agencia.criarConta(13, "conta 13", 100, (byte) 1, 0);
		agencia.criarConta(14, "conta 14", 100, (byte) 2, 0);
		agencia.criarConta(15, "conta 15", 100, (byte) 1, 0);
		agencia.criarConta(16, "conta 16", 100, (byte) 3, 50);
		agencia.criarConta(17, "conta 17", 100, (byte) 1, 0);
		agencia.criarConta(18, "conta 18", 100, (byte) 2, 0);
		agencia.criarConta(19, "conta 19", 100, (byte) 3, 60);
		agencia.criarConta(20, "conta 20", 100, (byte) 1, 0);

	}

	@Test(expected = ExcecaoContaInexistente.class)
	public void abrirContasIguais() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.criarConta(1, "conta 2", 100, (byte) 2, 0);
	}

	@Test(expected = ExcecaoFaltaEspaco.class)
	public void abrirVinteUmaContas() {
		agencia.criarConta(1, "conta 1", 100, (byte) 1, 0);
		agencia.criarConta(2, "conta 2", 100, (byte) 2, 0);
		agencia.criarConta(3, "conta 3", 100, (byte) 3, 10);
		agencia.criarConta(4, "conta 4", 100, (byte) 1, 0);
		agencia.criarConta(5, "conta 5", 100, (byte) 2, 0);
		agencia.criarConta(6, "conta 6", 100, (byte) 3, 20);
		agencia.criarConta(7, "conta 7", 100, (byte) 1, 0);
		agencia.criarConta(8, "conta 8", 100, (byte) 2, 0);
		agencia.criarConta(9, "conta 9", 100, (byte) 3, 30);
		agencia.criarConta(10, "conta 10", 100, (byte) 1, 0);
		agencia.criarConta(11, "conta 11", 100, (byte) 2, 0);
		agencia.criarConta(12, "conta 12", 100, (byte) 3, 40);
		agencia.criarConta(13, "conta 13", 100, (byte) 1, 0);
		agencia.criarConta(14, "conta 14", 100, (byte) 2, 0);
		agencia.criarConta(15, "conta 15", 100, (byte) 1, 0);
		agencia.criarConta(16, "conta 16", 100, (byte) 3, 50);
		agencia.criarConta(17, "conta 17", 100, (byte) 1, 0);
		agencia.criarConta(18, "conta 18", 100, (byte) 2, 0);
		agencia.criarConta(19, "conta 19", 100, (byte) 3, 60);
		agencia.criarConta(20, "conta 20", 100, (byte) 1, 0);
		agencia.criarConta(21, "conta 21", 100, (byte) 1, 0);
	}
}
